package net.sf.rose.file.util.resource;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import net.sf.rose.util.RoseRuntimeException;

/** 
 * 类说明 ：代替JDK自带的配置文件加载器
 * 特别地：
 * 1、支持配置文件参数的修改和保存
 * 2、参数列表是有顺序结构的
 * @author fengjian E-mail: 9110530@qq.com 
 * @version 创建时间：2015年9月25日 下午4:37:57 
 */
public class ResourceIniFile {

	private static Logger LOG = Logger.getLogger(ResourceIniFile.class);

	/** 配置文件参数是否被更新标志 */
	private boolean updateFlag = false;

	/** 配置文件对象 */
	private File file = null;

	/** */
	private List<ResourceBean> list = new ArrayList<>();

	/** 所有参数的键值对 */
	private Map<String, String> map = new LinkedHashMap<>();

	/** 父配置文件类 */
	private ResourceIniFile parent = null;

	/**
	 * 设置文件对象
	 * @param file 文件对象
	 */
	public void setFile(File file) {
		this.file = file;
	}

	/**
	 * 获取文件对象
	 * @return 文件对象
	 */
	public File getFile() {
		return file;
	}

	/**
	 * 将所有数据读入内存
	 * @param file 文件对象
	 */
	public void load(File file) {
		this.file = file;
		if (!file.exists()) {
			LOG.warn(file.toString() + "文件不存在！");
			return;
		}
		try {
			BufferedReader reader = new BufferedReader(new FileReader(file));
			String tempString, key, val = null;
			ResourceBean bean = null;
			// 必须是一行说明，一行键值对
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				if (tempString.length() == 0) {
					continue;
				}
				else if (tempString.charAt(0) == '#') {
					bean = new ResourceBean();
					bean.setDescription(tempString.substring(1));
					// System.out.print(tempString);
				} else {
					tempString = tempString.trim();
					int i = tempString.indexOf('=');
					if (i != -1) {
						key = tempString.substring(0, i).trim();
						val = tempString.substring(i + 1, tempString.length()).trim();
						bean.setKey(key);
						bean.setVal(val);
						list.add(bean);
						map.put(key, val);
						// System.out.println(key + '=' + val);
					}
				}
			}
			reader.close();
			LOG.warn("成功读取配置文件：" + file.getAbsolutePath());
		} catch (FileNotFoundException e) {
			String mess = "在指定的路径下没有找到配置文件：" + file.getAbsolutePath();
			LOG.error(mess, e);
			throw new RoseRuntimeException(mess, e);
		} catch (IOException e) {
			String mess = "读取配置文件：" + file.getAbsolutePath() + "时发生错误！";
			LOG.error(mess, e);
			throw new RoseRuntimeException(mess, e);
		}
	}

	/**
	 * 保存
	 * @return 是否成功
	 */
	public boolean save() {
		if (!updateFlag) {
			// return false;
		}
		try {
			BufferedWriter buf = new BufferedWriter(new FileWriter(file));
			for (ResourceBean bean : list) {
				buf.write("#" + bean.getDescription());
				buf.newLine();
				buf.write(bean.getKey() + '=' + bean.getVal());
				buf.newLine();
			}
			buf.flush();
			buf.close();
			return true;
		} catch (IOException e) {
			String mess = "保存配置文件：" + file.getAbsolutePath() + "时发生错误！";
			LOG.error(mess, e);
			return false;
		}
	}

	/**
	 * 设置父配置文件类
	 * @param parent 父配置文件实体
	 */
	public void setParent(ResourceIniFile parent) {
		this.parent = parent;
	}

	/**
	 * 返回父配置文件类
	 * @return 父配置文件实体
	 */
	public ResourceIniFile getParent() {
		return parent;
	}

	/**
	 * 设置属性
	 * @param bean 属性集
	 */
	public void set(ResourceBean bean) {
		String key = bean.getKey();
		for (ResourceBean b : list) {
			if (b.getKey().equals(key)) {
				b.setVal(bean.getVal());
				b.setDescription(bean.getDescription());
				updateFlag = true;
				return;
			}
		}
		list.add(bean);
		map.put(key, bean.getVal());
		updateFlag = true;
	}

	/**
	 * 取得属性
	 * @param key 主键
	 * @return 属性值
	 */
	public String get(String key) {
		String str = map.get(key);
		// 如果自身配置文件没有找到属性，而且父配置文件存在，则从父配置文件中找
		if (str == null) {
			return parent != null ? parent.get(key) : null;
		} else {
			return str.trim();
		}
	}

	/**
	 * 获取某个开关量
	 * 0：关闭；1：开启
	 * @param key 主键
	 * @return 属性值
	 */
	public boolean isOn(String key) {
		String str = this.get(key);
		return str == null ? false : str.equals("1");
	}

	/**
	 * 删除属性
	 * @param key 主键
	 */
	public void remove(String key) {
		for (int i = 0; i < list.size(); i++) {
			ResourceBean bean = list.get(i);
			if (bean.getKey().equals(key)) {
				list.remove(i);
				map.remove(key);
				updateFlag = true;
				return;
			}
		}
	}

	/**
	 * 返回所有键值
	 * @return 所有键值
	 */
	public List<ResourceBean> getAll() {
		return list;
	}

	/**
	 * 设置所有键值
	 * @param list 所有键值
	 */
	public void setAll(List<ResourceBean> list) {
		this.list = list;
		updateFlag = true;
	}

}
